
#ifndef ESTDLIB_H_INCLUDED
#define ESDLIB_H_INCLUDED
#include <string.h>
#define pi  3.1412
void reverse(char *s)
{
  int c, i, j;
  for(i=0,j=strlen(s)-1;i<j;i++,j--)
  {
  	 c=s[i];
  	 s[i]=s[j];
  	 s[j]=c;
  }
}

void intoa (int n, char *s)
{
		int i, sign;
		if((sign=n)<0)
			n=-n;
		i=0;
		do
		{
			s[i++]=n%10+'0';
		}while((n/=10)>0);
		if(sign<0)
		s[i++]='-';
		s[i]='\0';
		reverse(s);
}
float angle_conversion(float val)
{
    if(val>=-pi && val<0)
    {
        val=val+pi;
    }
    return val;
}
float *extract_colum(float **ptr,  int m, int n, int col_no)
{
  float *ptr_new;
  int i, j;
  ptr_new=(float*)calloc(m,sizeof(float));
  for(i=0;i<m;i++)
    {
      ptr_new[i]=ptr[i][col_no];
    }
  return ptr_new;
}

float getmin(float *point, int n)
{
  int r_ind;
  float min;
  min=point[0];
  for(r_ind=1;r_ind<n;r_ind++)
    {
      if(min>point[r_ind])
	{
	  min=point[r_ind];
	}
    }
  return min;
}

float getmax(float *point, int n)
{
  int r_ind;
  float max;
  max=point[0];
  for(r_ind=1;r_ind<n;r_ind++)
    {
      if(max<point[r_ind])
	{
	  max=point[r_ind];
	}
    }
  return max;
}
int getmaxInt(int *point, int n)
{
  int r_ind;
  int max;
  max=point[0];
  for(r_ind=1;r_ind<n;r_ind++)
    {
      if(max<point[r_ind])
	{
	  max=point[r_ind];
	}
    }
  return max;
}

float euclidean_distance(float **g, float  **u, int img_h, int img_w)
{
	float **distance,sum=0;
	int row, col;
	distance=alloc2Dfloat(img_h, img_w);
	for(row=0;row<img_h;row++)
	{
		for(col=0;col<img_w;col++)
		{

				distance[row][col]=(g[row][col]-u[row][col])*(g[row][col]-u[row][col]);
			sum=sum+distance[row][col];
		}
	}
return sqrt(sum);
}
double factorial(double val)
{

	if(val<=1)
		return 1;
	else
		return (val*factorial(val-1));
}
float gammafunction(float val)
{

	if(val<=1)
		return 1;
	else
		return (val*gammafunction(val-1));
}

float **normalize_int2Dfloat(int **mat, int height, int width, float max, float min)
{
	float **mat_new;
	int row, col, min_val, max_val;
	mat_new=alloc2Dfloat(height, width);
	min_val=mat[0][0];
	max_val=mat[0][0];
	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			if(min_val>mat[row][col])
			{
				min_val=mat[row][col];
			}
			if(max_val<mat[row][col])
			{
				max_val=mat[row][col];
			}
		}
	}
	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			mat_new[row][col]=((float)(mat[row][col]-min_val)/(max_val-min_val))*(max-min)+min;
		}
	}
	return mat_new;
}

float **normalize_float2Dfloat(float **mat, int height, int width, float max, float min)
{
	float **mat_new,min_val, max_val;
	int row, col;
	mat_new=alloc2Dfloat(height, width);
	min_val=mat[0][0];
	max_val=mat[0][0];

	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			if(min_val>mat[row][col])
			{
				min_val=mat[row][col];
			}
			if(max_val<mat[row][col])
			{
				max_val=mat[row][col];
			}
		}
	}

	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			mat_new[row][col]=((float)(mat[row][col]-min_val)/(max_val-min_val))*(max-min)+min;
		}
	}
	return mat_new;
}

int **normalize_float2Dint(float **mat, int height, int width, int max, int min)
{

	int **mat_new, row, col;
	float min_val, max_val;
	mat_new=alloc2Dint(height, width);
	min_val=mat[0][0];
	max_val=mat[0][0];
	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			if(min_val>mat[row][col])
			{
				min_val=mat[row][col];
			}
			if(max_val<mat[row][col])
			{
				max_val=mat[row][col];
			}
		}
	}
	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			mat_new[row][col]=(int)floor(((float)(mat[row][col]-min_val)/(max_val-min_val))*(max-min)+min);
		}
	}

	return mat_new;
}

int **normalize_int2Dint(int **mat, int height, int width, int max, int min)
{

	int **mat_new, row, col, min_val, max_val;
	mat_new=alloc2Dint(height, width);
	min_val=mat[0][0];
	max_val=mat[0][0];
	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			if(min_val>mat[row][col])
			{
				min_val=mat[row][col];
			}
			if(max_val<mat[row][col])
			{
				max_val=mat[row][col];
			}
		}
	}
	for(row=0;row<height;row++)
	{
		for(col=0;col<width;col++)
		{
			mat_new[row][col]=((float)(mat[row][col]-min_val)/(max_val-min_val))*(max-min)+min;
		}
	}
	return mat_new;
}
void intialize_time_seed()
{

	srand((unsigned)time(NULL));

}

float rand_num()
{
	float val;
	val=(float)rand()/RAND_MAX;
	return val;
}

float rand_num_range(int min, int max)
{
	float val;
	val=min+((float)rand()/(RAND_MAX))*(max-min);
	return val;
}
float *gammafcn(float m, float omega, int h)
{
	float *x, val1, val2,val3, phim, etam, val0, cond_val;
	int indx, i;
	x=alloc1Dfloat(h);

	for(indx=0;indx<h;indx++)
	{
		i=0;

		do
		{
			val0=(float)2.8173/(2.7183+i);
			val1=(float)(rand()/RAND_MAX)+0.00001;
			val2=(float)(rand()/RAND_MAX)+0.00001;
			val3=(float)(rand()/RAND_MAX)+0.00001;
			if(val1<val0)
			{
			   phim=pow(val1,(float)1/m);
			   etam=val3*pow(val1,(float)(m-1));

			}
			else
			{
			   phim=1-log(val1);
			   etam=val3*exp(-phim);

			}
			i++;
			cond_val=pow(val1,(float)(m-1))*exp(-phim);
		}while(etam>cond_val);
		x[indx]=omega*phim;
	}

	return x;

}

float *gamma_less_1(float m, float omega, int h)
{
	float x, u1,u2,v,t,b, *rand_val,y;
	int indx, flag;
	srand((unsigned)time(0));
	rand_val=alloc1Dfloat(h);
	t=0.07+0.75*(sqrt(1-m));
	b=1+(float)(exp(-t)*m)/t;
	for(indx=0;indx<h;indx++)
	{
		flag=0;
		do{
				u1=((float)rand()/RAND_MAX)*(1-0.00001)+0.00001;
				u2=((float)rand()/RAND_MAX)*(1-0.00001)+0.00001;
				v=b*u1;
				if(v<=1)
				{
					x=t*pow(v,(float)1/m);
					if(u2<=((float)(2-x)/(2+x)))
					{
						flag=1;
					}
					else if(u2<=exp(-x))
					{
					      flag=1;
					}
				}
				else
				{
					x=-log10(t*((b-v)/m));
					y=x/t;
					if(u2*(m+y*(1-m))<=1)
					{
					      flag=1;
					}
					else if(u2<=pow(y,m-1))
					{
					      flag=1;
					}
				}
		 }while(flag!=1);
		 rand_val[indx]=omega*x;

	}
	return rand_val;
}
float *gamma_greater_1(float m, float omega, int h)
{
	float u1, u2, v,c, x, *rand_val, temp1, temp2;
	int indx, flag;
	srand((unsigned)time(0));
	rand_val=alloc1Dfloat(h);
	for(indx=0;indx<h;indx++)
	{
		flag=0;
		do
		{
				u1=((float)rand()/RAND_MAX)*(1-0.00001)+0.00001;
				u2=((float)rand()/RAND_MAX)*(1-0.00001)+0.00001;
				v=(float)((m-((float)1/6*m))*u1)/((m-1)*u2);
				temp1=(float)(2*(u2-1))/(m-1)+v+((float)1/v);
				temp2=((float)(2*log(u2))/(m-1))-log(v)+v;
				x=(m-1)*v;
				if(temp1<=2)
				{
					flag=1;
				}
				else if(temp1<=1)
				{
					flag=1;
				}
		}while(flag!=1);
		rand_val[indx]=omega*x;

	}
	return rand_val;
}





float *nakagami_randnum(float m, float omega, int h)
{
	float *x,*y;
	int indx;
	y=alloc1Dfloat(h);
	if(m<1)
	 x=gamma_less_1(m,(float)m/omega, h);
	else
	 x=gamma_greater_1(m,(float)m/omega, h);
	for(indx=0;indx<h;indx++)
	{
		y[indx]=sqrt(x[indx]);
	}
	return y;
}

float **calgradx(float **im, int max_height, int max_width)
{

	int r_indx, c_indx;
	float **grad_x;
	grad_x=alloc2Dfloat(max_height, max_width);
	for(r_indx=1;r_indx<max_height-1;r_indx++)
	{
		for(c_indx=1;c_indx<max_width-1;c_indx++)
		{
			grad_x[r_indx][c_indx]=(float)(im[r_indx+1][c_indx]-im[r_indx-1][c_indx])/2;
		}
	}
return grad_x;

}
float **calgrady(float **im, int max_height, int max_width)
{

	int r_indx, c_indx;
	float **grad_y;
	grad_y=alloc2Dfloat(max_height, max_width);
	for(r_indx=1;r_indx<max_height-1;r_indx++)
	{
		for(c_indx=1;c_indx<max_width-1;c_indx++)
		{
			grad_y[r_indx][c_indx]=(float)(im[r_indx][c_indx+1]-im[r_indx][c_indx-1])/2;
		}
	}
return grad_y;

}
float **cal_lap(float **im, int max_height, int max_width)
{

	int r_indx, c_indx;
	float **lap;
	lap=alloc2Dfloat(max_height, max_width);
	for(r_indx=1;r_indx<max_height-1;r_indx++)
	{
		for(c_indx=1;c_indx<max_width-1;c_indx++)
		{
			lap[r_indx][c_indx]=(float)(im[r_indx][c_indx+1]+im[r_indx][c_indx-1]+im[r_indx+1][c_indx]+im[r_indx-1][c_indx]-4*im[r_indx][c_indx]);
		}
	}
return lap;

}

float getMaxVal(float **img_region, int max_height, int max_width)
{
	int r_indx, c_indx;
	float max_val;
	max_val=img_region[0][0];
	for(r_indx=0;r_indx<max_height;r_indx++)
	{
		for(c_indx=0;c_indx<max_width-1;c_indx++)
		{
			max_val=max_val<img_region[r_indx][c_indx] ? img_region[r_indx][c_indx] : max_val;
		}
	}
	return max_val;
}
int getmaxindx(float *diff_val, int length)
{
	int r_indx, max_indx;
	float max_val;
	max_val=diff_val[0];
	max_indx=0;
	for(r_indx=0;r_indx<length;r_indx++)
	{
		if(max_val<diff_val[r_indx])
		{
				max_val=diff_val[r_indx];
				max_indx=r_indx;
		}
	}
	return max_indx;
}

float median_func(float *vec, int length)
{
	int indx;
	float med_val;
	vec=sort1D(vec, length);
	indx=(int)floor((float)(length+1)/2);
	if((indx % 2)==0)
	{
		
		return (float)(vec[indx]+vec[indx+1])/2;
		
	}
	else
		return vec[indx];
}
float median_func2D(float **im, int height, int width)
{
	int indx, r_indx, c_indx, length;
	float med_val, *vec;
	vec=alloc1Dfloat(height*width);
	for(r_indx=0, length=0;r_indx<height;r_indx++)
	{
		for(c_indx=0;c_indx<width;c_indx++, length++)
		{
			vec[length]=im[r_indx][c_indx];
		}
	}
	vec=sort1D(vec, length);
	indx=(int)floor((float)(length+1)/2);
	if((indx % 2)==0)
		return (float)(vec[indx]+vec[indx+1])/2;
	
	else
		return vec[indx];
}





#else
#endif
